/*
 *  Filename:main.c
 *  Description:
 *
 *  Created on: 2017年2月27日
 *  Author: Asdf(825674301)
 */

#include "lsv_volume.h"
#include "lsv_conf.h"
#include "lsv_types.h"
#include "lsv_volume_gc.h"
#include "lsv_log.h"
#include "lsv_wbuffer.h"
#include "lsv_rcache.h"
#include "lsv_sysy_lib.h"

void test_volume_op() {

	lsv_ino_t i;
	lsv_volume_proto_t volume_proto;
	lsv_u32_t chunk_id;
	char buf1[LSV_CHUNK_SIZE];
	char buf2[LSV_CHUNK_SIZE];
	lsv_u32_t type = 0;

	volume_proto.ino = 10;
	volume_proto.size = ((lsv_u64_t) 1 << 40) * 256;
	lsv_volume_init(&volume_proto, LSV_SYS_CREATE);

	sprintf(buf1, "asdf!\n");

	lsv_volume_chunk_write(&volume_proto, buf1, type, &chunk_id);

	lsv_volume_chunk_read(&volume_proto, chunk_id, buf2);

	printf("%s", buf2);

	lsv_volume_chunk_update(&volume_proto, chunk_id, buf1, 5, 7);

	lsv_volume_chunk_read(&volume_proto, chunk_id, buf2);

	printf("%s", buf2);

	lsv_volume_chunk_malloc(&volume_proto, type, &chunk_id);

	lsv_volume_chunk_update(&volume_proto, chunk_id, buf1, 0, 7);

	lsv_volume_chunk_read(&volume_proto, chunk_id, buf2 + 7);

	printf("%s", buf2);

	lsv_volume_delete(&volume_proto);

	printf("ok!\n");
}

/*
 void test_log() {

 lsv_u32_t i;
 lsv_volume_proto_t volume_proto;
 lsv_u32_t chunk_id;
 char buf1[LSV_CHUNK_SIZE * 2 + sizeof(lsv_u32_t)];
 char buf2[LSV_CHUNK_SIZE];
 lsv_bitmap_unit_t bm = { 0 }, bm1 = { 0 };

 void*data = buf1; //
 lsv_io_hlog_arg_t* io_arg = (lsv_io_hlog_arg_t*) (buf1 + LSV_CHUNK_SIZE
 + sizeof(lsv_u32_t));
 lsv_u32_t *io_count = (lsv_u32_t*) (buf1 + LSV_CHUNK_SIZE);

 *io_count = 2 * sizeof(lsv_io_hlog_arg_t);
 io_arg[0].lba = 0;
 io_arg[0].size = LSV_PAGE_SIZE * 256;
 io_arg[1].lba = 1;
 io_arg[1].size = LSV_PAGE_SIZE * 2;

 sprintf(data, "asdf!\n");

 lsv_volume_create(&volume_proto);
 volume_proto.wbuffer_queue = thread_queue_init(10);
 lsv_log_init(&volume_proto);
 lsv_bitmap_init(&volume_proto);

 thread_queue_offer(volume_proto.wbuffer_queue, buf1);

 sleep(3);

 lsv_bitmap_paged_read(&volume_proto, io_arg[0].lba, &bm1);

 lsv_log_slog_read(&volume_proto, bm1.chunk_id, buf2);
 printf("data chk_id>%d:\n%s", bm1.chunk_id, buf2);

 //	lsv_log_slog_read(&volume_proto, 0, buf2);
 //	lsv_hlog_head_t *head = buf2;
 //	lsv_hlog_record_t *record = buf2 + LSV_HLOG_HEAD_SIZE;
 //	printf("log wbuf:\nid:%d,count:%d\n", head->id, head->record_num);
 //	for (i = 0; i < head->record_num; i++) {
 //		printf("record:<%ld,%d,%d>\n", record[i].lba, record[i].chkid,
 //				record[i].chkoffset);
 //	}

 //	lsv_log_slog_read(&volume_proto, 2, buf2);
 //	head = buf2;
 //	record = buf2 + LSV_HLOG_HEAD_SIZE;
 //	printf("hlog:\nid:%d,count:%d\n", head->id, head->record_num);
 //	for (i = 0; i < 10; i++) {
 //		printf("record:<%ld,%d,%d>\n", record[i].lba, record[i].chkid,
 //				record[i].chkoffset);
 //	}

 lsv_log_delete(&volume_proto);
 lsv_volume_delete(&volume_proto);
 }
 */
void test_bitmap1() {

	lsv_u32_t i;
	lsv_volume_proto_t volume_proto;
	lsv_u32_t first_chunk_id;
	lsv_bitmap_unit_t bitmap_unit_buf[LSV_CHUNK_SIZE / LSV_PAGE_SIZE];
	lsv_u64_t base;
	lsv_u32_t size;
	lsv_u32_t chunk_id, chunk_offset;

	volume_proto.ino = 11;
	volume_proto.size = ((lsv_u64_t) 1 << 40) * 256;
	lsv_volume_create(&volume_proto);
	lsv_volume_chunk_malloc(&volume_proto, LSV_PRIM_CHUNK_TYPE,
			&first_chunk_id);
	lsv_bitmap_init(&volume_proto, LSV_SYS_CREATE, 0);

	bitmap_unit_buf[0].chunk_id = 0;
	bitmap_unit_buf[0].chunk_off = 0;

	base = 4563402752;
	for (i = 2; i < 65536; i++) {

		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;

//		printf("%d,%d\n", bitmap_unit_buf[0].chunk_id,
//				bitmap_unit_buf[0].chunk_off);
		lsv_bitmap_batch_write(&volume_proto, base + i * 4096, 4096,
				bitmap_unit_buf);

	}
	for (i = 0; i < 2; i++) {
		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;

//		printf("%d,%d\n", bitmap_unit_buf[0].chunk_id,
//				bitmap_unit_buf[0].chunk_off);
		lsv_bitmap_batch_write(&volume_proto, base + i * 4096, 4096,
				bitmap_unit_buf);
	}

	for (i = 0; i < 65536; i++) {

		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;

//		printf("%d,%d\n", bitmap_unit_buf[0].chunk_id,
//				bitmap_unit_buf[0].chunk_off);
		lsv_bitmap_batch_write(&volume_proto, base - i * 4096, 4096,
				bitmap_unit_buf);

	}

	for (i = 65535; i > 0; i--) {
		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;
		lsv_bitmap_batch_write(&volume_proto, base - i * 4096, 4096,
				bitmap_unit_buf);
	}

	printf("=============\n");
	for (i = 0; i < 65536; i++) {
		lsv_bitmap_paged_lookup(&volume_proto, base + i * 4096, &chunk_id,
				&chunk_offset);
		printf("%d,%d\n", chunk_id, chunk_offset);
		if (chunk_id != i || chunk_offset != i) {
			printf("err\n");
		}
	}

	lsv_bitmap_deinit(&volume_proto);
	lsv_volume_delete(&volume_proto);
}

void test_bitmap() {

	lsv_u32_t i;
	lsv_volume_proto_t volume_proto;
	lsv_u32_t first_chunk_id;
	lsv_bitmap_unit_t bitmap_unit_buf[LSV_CHUNK_SIZE / LSV_PAGE_SIZE];
	lsv_u64_t base;
	lsv_u32_t size;
	lsv_u32_t chunk_id, chunk_offset;

	volume_proto.ino = 11;
	volume_proto.size = ((lsv_u64_t) 1 << 40) * 256;
	lsv_volume_create(&volume_proto);
	lsv_volume_chunk_malloc(&volume_proto, LSV_PRIM_CHUNK_TYPE,
			&first_chunk_id);
	lsv_bitmap_init(&volume_proto, LSV_SYS_CREATE, 0);

	bitmap_unit_buf[0].chunk_id = 0;
	bitmap_unit_buf[0].chunk_off = 0;

	base = 4563402752;
	for (i = 2; i < 65536; i++) {

		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;

//		printf("%d,%d\n", bitmap_unit_buf[0].chunk_id,
//				bitmap_unit_buf[0].chunk_off);
		lsv_bitmap_batch_write(&volume_proto, base + i * 4096, 4096,
				bitmap_unit_buf);

	}
	for (i = 0; i < 2; i++) {
		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;

//		printf("%d,%d\n", bitmap_unit_buf[0].chunk_id,
//				bitmap_unit_buf[0].chunk_off);
		lsv_bitmap_batch_write(&volume_proto, base + i * 4096, 4096,
				bitmap_unit_buf);
	}

	for (i = 0; i < 65536; i++) {

		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;

//		printf("%d,%d\n", bitmap_unit_buf[0].chunk_id,
//				bitmap_unit_buf[0].chunk_off);
		lsv_bitmap_batch_write(&volume_proto, base - i * 4096, 4096,
				bitmap_unit_buf);

	}

	for (i = 65535; i > 0; i--) {
		bitmap_unit_buf[0].chunk_id = i;
		bitmap_unit_buf[0].chunk_off = i;
		lsv_bitmap_batch_write(&volume_proto, base - i * 4096, 4096,
				bitmap_unit_buf);
	}

	printf("=============\n");
	for (i = 0; i < 65536; i++) {
		lsv_bitmap_paged_lookup(&volume_proto, base + i * 4096, &chunk_id,
				&chunk_offset);
		printf("%d,%d\n", chunk_id, chunk_offset);
		if (chunk_id != i || chunk_offset != i) {
			printf("err\n");
		}
	}

	lsv_bitmap_deinit(&volume_proto);
	lsv_volume_delete(&volume_proto);
}

/*
 void test_rw() {

 lsv_s32_t rc = 0;
 lsv_u32_t i;
 lsv_volume_proto_t volume_proto;
 lsv_u32_t first_chunk_id;
 char buf1[LSV_CHUNK_SIZE];
 char buf2[LSV_CHUNK_SIZE];
 char buf3[LSV_CHUNK_SIZE];
 lsv_u64_t offset, off;
 lsv_u32_t size;
 lsv_u64_t off_arr;
 lsv_u32_t chunk_id, chunk_offset;

 sprintf(buf1, "asdf!\n");

 lsv_volume_create(&volume_proto);
 lsv_volume_malloc(&volume_proto, 0, &first_chunk_id);
 volume_proto.wbuffer_queue = thread_queue_init(10);
 lsv_log_init(&volume_proto);
 lsv_bitmap_init(&volume_proto);
 lsv_wbuffer_init(&volume_proto);
 lsv_rcache_init(&volume_proto);

 offset = 0;
 size = LSV_CHUNK_SIZE;

 for (i = 0; i < 100; i++, offset += LSV_PAGE_SIZE) {

 memset(buf1, i, LSV_CHUNK_SIZE);
 *((int*) buf1) = i;

 lsv_wbuffer_insert(&volume_proto, offset, size, buf1);
 printf("write>%d\n", i);
 sleep(3);

 for (off = 0; off < size; off += LSV_PAGE_SIZE) {
 rc = lsv_wbuffer_readpage(&volume_proto, offset + off,
 LSV_PAGE_SIZE, buf2 + off);
 if (rc < 0) {
 DINFO("read:wbuffer_readpage:%d\n", rc);
 return;
 } else if (rc > 0) {
 DINFO("wbuffer_read  %d\n", rc);
 lsv_bitmap_paged_lookup(&volume_proto, offset + off, &chunk_id,
 &chunk_offset);
 lsv_rcache_lookup(&volume_proto, chunk_id, chunk_offset,
 LSV_PAGE_SIZE, buf3 + off);
 continue;
 }

 lsv_bitmap_paged_lookup(&volume_proto, offset + off, &chunk_id,
 &chunk_offset);
 DINFO("slog_info_read  %ld,%d,%d\n", offset + off, chunk_id,
 chunk_offset);

 lsv_rcache_lookup(&volume_proto, chunk_id, chunk_offset,
 LSV_PAGE_SIZE, buf2 + off);

 }
 rc = memcmp(buf1, buf2, size);
 if (rc) {
 printf("ASDF==== %d,%d,%d\n", *((int*) buf1), *((int*) buf2),
 *((int*) buf3));
 printf("%d\n", i);
 }
 }

 lsv_wbuffer_release(&volume_proto);
 lsv_bitmap_deinit(&volume_proto);
 lsv_log_delete(&volume_proto);
 lsv_volume_delete(&volume_proto);
 }
 */

void print_vol_gc_info(lsv_volgc_avachk_list_t* vachk_list) {
	printf("<%d,%d>,<%d,%d>,%d\n", vachk_list->malloc_record,
			(vachk_list->record + vachk_list->malloc_record)->count,
			vachk_list->free_record,
			(vachk_list->record + vachk_list->free_record)->count,
			vachk_list->next_chkid);
}

void test_volume_gc1() {

	lsv_s32_t rc = 0;
	lsv_u32_t i;
	lsv_volume_proto_t _volume_proto, *volume_proto;
	lsv_volgc_info_t *volgc_info = NULL;
	lsv_volgc_avachk_list_t *vachk_list = NULL;
	lsv_u8_t type;
	lsv_u32_t chunk_id;

	volume_proto = &_volume_proto;
	volume_proto->ino = 10;
	volume_proto->size = ((lsv_u64_t) 1 << 20) * 262144;
	lsv_volume_create(volume_proto);

	type = 1;
	volgc_info = volume_proto->volgc_info;
	vachk_list = volgc_info->avachk_list + type;

//		lsv_volume_volgc_free(volume_proto, type, i + 1);
//	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);

	for (i = 0; i < LSV_VOLGC_RECORD_AVACHK_NUM - 1; i++) {
		lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
		if (i != chunk_id)
			printf("%d\n", chunk_id);
	}
	print_vol_gc_info(vachk_list);
//	<0,1>,<1,0>,0

	for (i = 0; i < LSV_VOLGC_RECORD_AVACHK_NUM; i++) {
		lsv_volume_volgc_free(volume_proto, type, i + 1);
	}
	print_vol_gc_info(vachk_list);
	//	<0,1>,<1,262142>,0

	lsv_volume_volgc_free(volume_proto, type, chunk_id);
	print_vol_gc_info(vachk_list);
	//	<0,1>,<1,1>,1

	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);
	//	<1,1>,<1,1>,1

	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);
	//	<1,2>,<0,0>,1   tail has 2

	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);
	//	<1,1>,<0,0>,1

	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);
	//	<0,0>,<0,0>,1

	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);
	//	<0,262141>,<1,0>,0

	for (i = 0; i < LSV_VOLGC_RECORD_AVACHK_NUM - 1; i++) {
		lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	}
	print_vol_gc_info(vachk_list);
	//	<1,0>,<1,0>,0

	//no
	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);

	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);

	lsv_volume_delete(volume_proto);
	printf("ok!\n");
}

void test_volume_gc2() {

	lsv_s32_t rc = 0;
	lsv_u32_t i;
	lsv_volume_proto_t _volume_proto, *volume_proto;
	lsv_volgc_info_t *volgc_info = NULL;
	lsv_volgc_avachk_list_t *vachk_list = NULL;
	lsv_u8_t type;
	lsv_u32_t chunk_id;

	volume_proto = &_volume_proto;
	volume_proto->ino = 10;
	volume_proto->size = ((lsv_u64_t) 1 << 40) * 256;
	lsv_volume_create(volume_proto);

	type = 1;
	volgc_info = volume_proto->volgc_info;
	vachk_list = volgc_info->avachk_list + type;

//		lsv_volume_volgc_free(volume_proto, type, i + 1);
//	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);

	for (i = 0; i < LSV_VOLGC_RECORD_AVACHK_NUM * 10; i++) {
		lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
		if (i != chunk_id)
			printf("%d\n", chunk_id);
	}
	print_vol_gc_info(vachk_list);
	//<0,0>,<0,0>,0

	for (i = 0; i < LSV_VOLGC_RECORD_AVACHK_NUM * 15; i++) {
		lsv_volume_volgc_free(volume_proto, type, i + 1);
	}
	print_vol_gc_info(vachk_list);
	//<0,262142>,<1,262142>,***

	lsv_volume_volgc_free(volume_proto, type, 777);
	print_vol_gc_info(vachk_list);
//	<0,262142>,<1,1>,***

	lsv_volume_delete(volume_proto);
	printf("ok!\n");
}

void test_volume_gc3() {

	lsv_s32_t rc = 0;
	lsv_u32_t i;
	lsv_volume_proto_t _volume_proto, *volume_proto;
	lsv_volgc_info_t *volgc_info = NULL;
	lsv_volgc_avachk_list_t *vachk_list = NULL;
	lsv_u8_t type;
	lsv_u32_t chunk_id;

	volume_proto = &_volume_proto;
	volume_proto->ino = 10;
	volume_proto->size = ((lsv_u64_t) 1 << 40) * 256;
	volume_proto->u.volume_page_id = 1;
	lsv_volume_create(volume_proto);

	type = 1;
	volgc_info = volume_proto->volgc_info;
	vachk_list = volgc_info->avachk_list + type;

	for (i = 0; i < LSV_VOLGC_RECORD_AVACHK_NUM; i++) {
		lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	}
	print_vol_gc_info(vachk_list);
	//<1,0>,<1,0>,0

	for (i = 0; i < LSV_VOLGC_RECORD_AVACHK_NUM; i++) {
		lsv_volume_volgc_free(volume_proto, type, i + 2);
	}
	print_vol_gc_info(vachk_list);
//	<1,262142>,<1,262142>,0

	lsv_volume_volgc_free(volume_proto, type, 3);
	print_vol_gc_info(vachk_list);
	//<1,262142>,<0,1>,0

	lsv_volume_download(volume_proto);
	if (volume_proto->volgc_info != NULL) {
		printf("err!\N");
	}
	lsv_volume_upload(volume_proto);

	volgc_info = volume_proto->volgc_info;
	vachk_list = volgc_info->avachk_list + type;
	printf("%d\n", volgc_info->tail);
	//262142
	print_vol_gc_info(vachk_list);
	//<0,0>,<0,0>,2

	lsv_volume_volgc_malloc(volume_proto, type, &chunk_id);
	print_vol_gc_info(vachk_list);
	//<0,262141>,<1,0>,3

	lsv_volume_delete(volume_proto);
	printf("ok!\n");
}

test_lg_bm() {
	lsv_log_page_bitmap_t _lg_bm, *lg_bm;
	lg_bm = &_lg_bm;

	lsv_u32_t i, j;
	lsv_u8_t idx;

	lp_bitmap_init(lg_bm);

	for (i = 0; i < 256; i++) {
		idx = i;

		if (lp_bitmap_get(lg_bm, idx) != 0) {
			printf("a,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));
			for (j = 0; j < LSV_LOG_PAGE_BITMAP_SIZE / 8; j++) {
				printf("ssss>%d\n", lg_bm->bitmap[j]);
			}
		}

		lp_bitmap_used(lg_bm, idx)
		if (lp_bitmap_get(lg_bm, idx) == 0)
			printf("b,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

		lp_bitmap_used(lg_bm, idx)
		if (lp_bitmap_get(lg_bm, idx) == 0)
			printf("c,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

		lp_bitmap_unuse(lg_bm, idx)
		if (lp_bitmap_get(lg_bm, idx) != 0)
			printf("d,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

		lp_bitmap_unuse(lg_bm, idx)
		if (lp_bitmap_get(lg_bm, idx) != 0)
			printf("e,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

		lp_bitmap_used(lg_bm, idx)
		if (lp_bitmap_get(lg_bm, idx) == 0)
			printf("f,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

		lp_bitmap_unuse(lg_bm, idx)
		if (lp_bitmap_get(lg_bm, idx) != 0)
			printf("g,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

		lp_bitmap_used(lg_bm, idx)
		if (lp_bitmap_get(lg_bm, idx) == 0)
			printf("h,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

//		lp_bitmap_unuse(lg_bm, idx)
//		if (lp_bitmap_get(lg_bm, idx) != 0)
//			printf("i,%d,%d\n", idx, lp_bitmap_get(lg_bm, idx));

		if (lg_bm->use_count != idx + 1) {
			printf("j,set:%d\n", lg_bm->use_count);
		}
	}

	printf("set:%d\n", lg_bm->use_count);

	printf("ok!\n");
}

void test_log_define() {
	printf("%d\n", sizeof(lsv_log_head_t));
	printf("%d\n", sizeof(lsv_log_hlog_t));
	printf("%d\n", sizeof(lsv_log_slog_t));
	printf("%d\n", sizeof(lsv_log_proto_t));
	printf("%d\n", sizeof(lsv_loggc_old_storage_record_t));
	printf("%d\n", LSV_LOG_PAGE_SIZE);
	assert(LSV_LOG_HEAD_AREA > sizeof(lsv_log_head_t));
	assert(LSV_LOG_HLOG_SIZE == sizeof(lsv_log_hlog_t));
	assert(LSV_LOG_SLOG_SIZE == sizeof(lsv_log_slog_t));
	assert(LSV_LOG_PAGE_SIZE == 255);
	assert(LSV_CHUNK_SIZE== sizeof(lsv_loggc_old_storage_record_t));

	printf("==========\n");

	lsv_log_proto_t _log_proto, *log_proto;
	log_proto = &_log_proto;

	log_proto->log = NULL;
	lsv_log_proto_link(log_proto);

	printf("%d\n", log_proto->head);
	printf("%d\n", log_proto->hlog);
	printf("%d\n", log_proto->slog);

	printf("ok!\n");
}

//cmp volctrl and chunkid
static int _lsv_loggc_volctrl_cmp(const void *_volctrl, const void *_chunkid) {
	lsv_loggc_logctrl_t *volctrl = _volctrl;
	lsv_u32_t *chunkid = _chunkid;
	if (volctrl->chunk_id > *chunkid)
		return 1;
	else if (volctrl->chunk_id < *chunkid)
		return -1;
	else
		return 0;
}
//change key to uint32
static uint32_t __chkid2key(const void *_chunkid) {
	return *(uint32_t*) _chunkid;
}

static hashtable_entry_t *hashtable_lookup2(hashtable_t t,
		const void *comparator, uint32_t k,
		int (*compare_func)(const void *, const void *), int *success) {
	uint32_t key = k % t->size;
	hashtable_entry_t *i;

	for (i = &(t->entries[key]); *i; i = &((*i)->next)) {
		if (compare_func && ((*i)->key == k))
			if ((*t->compare_func)((*i)->value, comparator) == 0) {
				*success = 1;
				return i;
			}
	}

	*success = 0;

	return &(t->entries[key]);
}

void *hash_table_find2(hashtable_t t, const void *comparator) {
	int success;
	hashtable_entry_t *entry;
	void* aaa;

	entry = hashtable_lookup2(t, comparator, (*t->key_func)(comparator),
			t->compare_func, &success);

	if (success) {
		return (*entry)->value;
	}

	return NULL;
}

void test_hash_tab() {
	lsv_s32_t rc = 0;

	hashtable_t log_ctrl_tab;
	log_ctrl_tab = hash_create_table(_lsv_loggc_volctrl_cmp, __chkid2key,
			"LSV_LOGGC_LOGCTRL_TAB");
	if (log_ctrl_tab == NULL) {
		//	                ret = ENOMEM;
		printf("err");
	}

	lsv_loggc_logctrl_t volctrl;
	volctrl.chunk_id = 10;
	volctrl.gc_count = 12;
	volctrl.gc_vaule = 14;
	rc = hash_table_insert(log_ctrl_tab, &volctrl, &volctrl.chunk_id, 0);

	lsv_u32_t chunk_id = 10;
	lsv_loggc_logctrl_t* volctrl2;

	volctrl2 = (lsv_loggc_logctrl_t*) hash_table_find(log_ctrl_tab, &chunk_id);
	if (volctrl2 == &volctrl) {
		printf("okkkk!\n");
	}

	if (NULL != volctrl2) {
		printf("%d,%d,%d\n", volctrl.chunk_id, volctrl.gc_count,
				volctrl.gc_vaule);
	}

//	hash_destroy_table(log_ctrl_tab, void (*thunk)(void *))
	printf("ok!\n");
}

static inline void __lsv_log_gc_gc_heap_up(lsv_loggc_gc_heap_t *gc_heap,
		lsv_u32_t pos) {

	lsv_u32_t i;
	lsv_loggc_logctrl_t **heap;
	lsv_loggc_logctrl_t *logctrl;
	lsv_u32_t parent;

	heap = gc_heap->heap;
	logctrl = heap[pos];
	while (pos > 0) {
		parent = (pos - 1) >> 1;
		if (heap[parent]->gc_vaule >= logctrl->gc_vaule) {
			break;
		}
		heap[pos] = heap[parent];
		pos = parent;
	}
	heap[pos] = logctrl;
}

static inline void __lsv_log_gc_gc_heap_down(lsv_loggc_gc_heap_t *gc_heap,
		lsv_u32_t pos) {

	lsv_u32_t i;
	lsv_loggc_logctrl_t **heap;
	lsv_loggc_logctrl_t *logctrl;
	lsv_u32_t child, right, half;

	heap = gc_heap->heap;

	half = gc_heap->count >> 1;
	logctrl = heap[pos];
	while (pos < half) {
		child = (pos << 1) + 1;
		right = child + 1;
		if (right < LSV_LOGGC_GC_HEAP_SIZE
				&& heap[right]->gc_vaule > heap[child]->gc_vaule) {
			child = right;
		}
		if (logctrl->gc_vaule >= heap[child]->gc_vaule) {
			break;
		}
		heap[pos] = heap[child];
		pos = child;
	}
	heap[pos] = logctrl;
}

void test_heap() {
	lsv_loggc_gc_heap_t _gc_heap, *gc_heap;
	lsv_loggc_logctrl_t data[LSV_LOGGC_GC_HEAP_SIZE];
	lsv_u32_t i;
	gc_heap = &_gc_heap;
	for (i = 0; i < LSV_LOGGC_GC_HEAP_SIZE; i++) {
		data[i].chunk_id = i + 11;
		data[i].gc_vaule = i;

		gc_heap->heap[gc_heap->count] = data + i;
		__lsv_log_gc_gc_heap_up(gc_heap, gc_heap->count);
		gc_heap->count++;
	}
	for (i = 0; i < LSV_LOGGC_GC_HEAP_SIZE; i++) {
		printf("%d,", gc_heap->heap[i]->chunk_id);
	}
	printf("\n");
	for (i = 0; i < LSV_LOGGC_GC_HEAP_SIZE; i++) {
		printf("%d,", gc_heap->heap[0]->chunk_id);
		gc_heap->heap[0] = gc_heap->heap[--gc_heap->count];
		__lsv_log_gc_gc_heap_down(gc_heap, 0);
	}
	printf("\n");
}

void test_log_gc1() {
	lsv_s32_t rc = 0;
	lsv_u32_t i;
	lsv_volume_proto_t _volume_proto, *volume_proto;
	lsv_log_proto_t _log_ptoto, *log_ptoto;
	char buf1[LSV_CHUNK_SIZE];
	lsv_u32_t chunk_id;

	volume_proto = &_volume_proto;
	volume_proto->ino = 10;
	volume_proto->size = ((lsv_u64_t) 1 << 40) * 256;
	rc = lsv_volume_create(volume_proto);
	rc = lsv_volume_chunk_malloc(volume_proto, LSV_PRIM_CHUNK_TYPE, &chunk_id);
	rc = lsv_log_init(volume_proto, LSV_SYS_CREATE);

	log_ptoto = &_log_ptoto;
	log_ptoto->log = buf1;
	lsv_log_proto_link(log_ptoto);

	//check return 1;no gc in fullgc
	log_ptoto->head->page_count = LSV_LOG_PAGE_SIZE;
	for (i = 0; i < LSV_LOG_PAGE_SIZE; i++) {
		log_ptoto->hlog[i].lba = i;
	}

	for (i = 0; i < LSV_LOGGC_OLD_STORAGE_CHUNK_NUM + 25; i++) {
		log_ptoto->chunk_id = i + 1;
		rc = lsv_log_gc_log_add(volume_proto, log_ptoto);
		rc = lsv_log_gc(volume_proto, LSV_LOGGC_GC_TYPE_NORMAL);
	}

	for (i = 0; i < LSV_LOGGC_OLD_STORAGE_CHUNK_NUM / 20; i++) {
		rc = lsv_log_fullgc(volume_proto);
	}

	rc = lsv_log_fullgc(volume_proto);
	rc = lsv_log_fullgc(volume_proto);
	rc = lsv_log_fullgc(volume_proto);

	lsv_log_delete(volume_proto);
	lsv_volume_delete(volume_proto);

	printf("ok!\n");
}

void test_log_gc2() {
	lsv_s32_t rc = 0;
	lsv_u32_t i, j;
	lsv_log_info_t *log_info = NULL;
	lsv_loggc_context_t *loggc_context = NULL;
	lsv_volume_proto_t _volume_proto, *volume_proto;
	lsv_log_proto_t _log_ptoto, *log_ptoto;
	char buf1[LSV_CHUNK_SIZE];
	char buf2[LSV_CHUNK_SIZE];
	lsv_u32_t chunk_id;
	lsv_u32_t storage_count, storage_ready_chunk_count;
	lsv_u8_t test_data;

	//check 25% return 1
	//LSV_LOGGC_CHECK_QUEUE_SIZE (2)
	// LSV_LOGGC_GC_HEAP_SIZE (7)
	test_data = 19;
	storage_count = 0;
	storage_ready_chunk_count = 5;

	volume_proto = &_volume_proto;
	volume_proto->ino = 10;
	volume_proto->size = ((lsv_u64_t) 1 << 40) * 256;
	rc = lsv_volume_create(volume_proto);
	rc = lsv_volume_chunk_malloc(volume_proto, LSV_PRIM_CHUNK_TYPE, &chunk_id);
	rc = lsv_log_init(volume_proto, LSV_SYS_CREATE);

	log_ptoto = &_log_ptoto;
	log_ptoto->log = buf1;
	lsv_log_proto_link(log_ptoto);

	log_ptoto->head->page_count = LSV_LOG_PAGE_SIZE;
	for (i = 0; i < LSV_LOG_PAGE_SIZE; i++) {
		log_ptoto->hlog[i].lba = i;
	}
	log_ptoto->slog[0].page[0] = test_data;

	for (i = 0; i < 8; i++) {
		log_ptoto->chunk_id = i + 1;
		lsv_volume_chunk_update(volume_proto, log_ptoto->chunk_id, buf1, 0,
		LSV_CHUNK_SIZE);
		rc = lsv_log_gc_log_add(volume_proto, log_ptoto);
		rc = lsv_log_gc(volume_proto, LSV_LOGGC_GC_TYPE_NORMAL);
	}

	lsv_log_download(volume_proto);
	lsv_log_upload(volume_proto);

	lsv_volume_chunk_read(volume_proto, 262142, buf2);
	log_ptoto->log = buf2;
	lsv_log_proto_link(log_ptoto);
	printf("merge info %u\n", log_ptoto->slog[0].page[0]);
	printf("merge info %u\n", log_ptoto->slog[63].page[0]);
	printf("merge info %u\n", log_ptoto->slog[126].page[0]);
	printf("merge info %u\n", log_ptoto->slog[189].page[0]);
	assert(log_ptoto->slog[0].page[0] == test_data);
	assert(log_ptoto->slog[63].page[0] == test_data);
	assert(log_ptoto->slog[126].page[0] == test_data);
	assert(log_ptoto->slog[189].page[0] == test_data);

	log_info = (lsv_log_info_t*) volume_proto->log_info;
	loggc_context = log_info->loggc_context;

	printf("storage_count %u\n", storage_count);
	printf("storage_ready_chunk_count %u\n", storage_ready_chunk_count);
	assert(storage_count == loggc_context->old_storage.count);
	assert(
			storage_ready_chunk_count
					== loggc_context->old_storage.ready_chunk.count);

	lsv_log_delete(volume_proto);
	lsv_volume_delete(volume_proto);

	printf("ok!\n");
}

void test_log_gc3() {
	lsv_s32_t rc = 0;
	lsv_u32_t i, j;
	lsv_volume_proto_t _volume_proto, *volume_proto;
	lsv_u32_t chunk_id;

	volume_proto = &_volume_proto;
	volume_proto->ino = 10;
	volume_proto->size = ((lsv_u64_t) 1 << 40) * 256;

	rc = lsv_volume_create(volume_proto);
	rc = lsv_volume_chunk_malloc(volume_proto, LSV_PRIM_CHUNK_TYPE, &chunk_id);
	rc = lsv_log_init(volume_proto, LSV_SYS_CREATE);

	lsv_log_download(volume_proto);
	lsv_log_upload(volume_proto);

	lsv_log_delete(volume_proto);
	lsv_volume_delete(volume_proto);

	printf("ok!\n");
}
int main() {

	lsv_u32_t i = 0;
//	for (i = 0; i < 100; i++)

//	test_volume_op();
//	test_log(); old
//	test_bitmap();
////	test_rw();old
//
//	test_volume_gc1();
//	test_volume_gc2();
//	test_volume_gc3();

//	test_lg_bm();
//	test_hash_tab();
//	test_log_define();
//	test_heap();
//	test_log_gc1();
//	test_log_gc2();//old
	test_log_gc3();	//old

	printf("%d>ok!\n", i);

	return 0;
}
